package com.raja.servingStation.common.redis;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import redis.clients.jedis.*;

import java.util.ArrayList;
import java.util.List;


/**
 * redis工具类
 * @author zxp
 *
 */
public final class RedisUtil {
	private static final Log logger = LogFactory.getLog(RedisUtil.class);
	//Redis服务器IP
	private static String ADDR = PropertiesUtil.getValue("REDIS_HOST");//115.29.245.240

	//Redis的端口号
	private static int PORT = Integer.parseInt(PropertiesUtil.getValue("REDIS_PORT"));

	//访问密码
	private static String AUTH = PropertiesUtil.getValue("REDIS_PWD");

	//可用连接实例的最大数目，默认值为8；
	//如果赋值为-1，则表示不限制；如果pool已经分配了maxActive个jedis实例，则此时pool的状态为exhausted(耗尽)。
	private static int MAX_ACTIVE = Integer.parseInt(PropertiesUtil.getValue("REDIS_MAX_ACTIVE"));

	//控制一个pool最多有多少个状态为idle(空闲的)的jedis实例，默认值也是8。
	private static int MAX_IDLE = Integer.parseInt(PropertiesUtil.getValue("REDIS_MAX_IDLE"));

	//等待可用连接的最大时间，单位毫秒，默认值为-1，表示永不超时。如果超过等待时间，则直接抛出JedisConnectionException；
	private static int MAX_WAIT = Integer.parseInt(PropertiesUtil.getValue("REDIS_MAX_WAIT"));

	private static int TIMEOUT = Integer.parseInt(PropertiesUtil.getValue("REDIS_TIMEOUT"));

	//在borrow一个jedis实例时，是否提前进行validate操作；如果为true，则得到的jedis实例均是可用的；
	private static boolean TEST_ON_BORROW = true;

	private static JedisPool jedisPool = null;

	// 返回值常量
	public static final int RET_SUCCESS = 1;
	public static final int RET_FAIL = 0;
	public static final int timeout = 1*60*60;

	/**
	 * 初始化Redis连接池
	 */
	static {
		try {
			JedisPoolConfig config = new JedisPoolConfig();
//			config.setMaxActive(MAX_ACTIVE);
			config.setMaxTotal(MAX_ACTIVE);
			config.setMaxIdle(MAX_IDLE);
//			config.setMaxWait(MAX_WAIT);
			config.setMaxWaitMillis(MAX_WAIT);
			config.setTestOnBorrow(TEST_ON_BORROW);
			jedisPool = new JedisPool(config, ADDR, PORT, TIMEOUT, AUTH);
		} catch (Exception e) {
			logger.error(e);
		}
	}

	/**
	 * 获取Jedis实例
	 * @return
	 */
	public synchronized static Jedis getJedis() {
		try {
			if (jedisPool != null) {
				Jedis resource = jedisPool.getResource();
				return resource;
			} else {
				return null;
			}
		} catch (Exception e) {
			logger.error(e);
			return null;
		}
	}

	/**
	 * 释放jedis资源
	 * @param jedis
	 */
	public static void returnResource(final Jedis jedis) {
		if (jedis != null) {
			jedisPool.returnResource(jedis);
		}
	}

	/**
	 * 根据key设置字符串值
	 * @param key
	 * @param value
	 * @return
	 * @throws Exception
	 */
	public static void setString(String key, String value) throws Exception {

		Jedis jedis = getJedis();

		if (jedis != null) {
			try {
				jedis.set(key, value);
			} catch (Exception e) {
				logger.error("jedis.setString error", e);
			} finally {
				if (jedis != null) {
					try {
						returnResource(jedis);
					} catch (Exception e1) {
						logger.error("returnResource error", e1);
					}
				}
			}
		}

	}
	/**
	 * 根据key设置字符串值
	 * @param key
	 * @param value
	 * @param time 定时
	 * @return
	 * @throws Exception
	 */
	public static void setString(String key,int time, String value) throws Exception {

		Jedis jedis = getJedis();

		if (jedis != null) {
			try {
				jedis.setex(key,time, value);
			} catch (Exception e) {
				logger.error("jedis.setString error", e);
			} finally {
				if (jedis != null) {
					try {
						returnResource(jedis);
					} catch (Exception e1) {
						logger.error("returnResource error", e1);
					}
				}
			}
		}

	}
	/**
	 * 根据key获取字符串值
	 * @param key
	 * @return
	 * @throws Exception
	 */
	public static String getString(String key) throws Exception {
		String result = "";

		Jedis jedis = getJedis();

		if (jedis != null) {
			try {
				result = jedis.get(key);
			} catch (Exception e) {
				logger.error("jedis.set error", e);
			} finally {
				if (jedis != null) {
					try {
						returnResource(jedis);
					} catch (Exception e1) {
						logger.error("returnResource error", e1);
					}
				}
			}
		}

		return result;
	}

	/**
	 * 批量存入redis
	 * @param keys
	 * @param values
	 * @throws Exception
	 */
	public static void setBytes(List<byte[]> keys,List<byte[]> values) throws Exception {
		Jedis jedis = getJedis();

		byte[] key = new byte[30];
		byte[] value = new byte[30];
		try {
			//遍历参数list
			for (int i = 0; i < keys.size(); i++) {
				//获取每一个key value
				key = keys.get(i);
				value = values.get(i);
				jedis.set(key, value);
			}
		} catch (Exception e) {
			logger.error("jedis.setBytes error", e);
		} finally {
			if (jedis != null) {
				try {
					returnResource(jedis);
				} catch (Exception e1) {
					logger.error("returnResource error!");
				}
			}
		}



	}

	/**
	 * 通过管道批量设置键值
	 * @param keys 键值列表
	 * @param values 设置值列表
	 * @throws Exception
	 */
	public static void setBytesBatch(final List<String> keys, final List<byte[]> values)
			throws Exception {
		Jedis jedis = getJedis();

		try {
			Pipeline pipe = jedis.pipelined();

			for (int i = 0; i < keys.size(); i++) {
				pipe.set(keys.get(i).getBytes(), values.get(i));
			}

			pipe.sync();

		} catch (Exception e) {
			logger.error("jedis.setBytesBatch error", e);
		} finally {
			if (jedis != null) {
				try {
					returnResource(jedis);
				} catch (Exception e1) {
					logger.error("returnResource error", e1);
				}
			}
		}



	}


	/**
	 * 根据key值获取byte[]
	 * @param key
	 * @return
	 * @throws Exception
	 */
	public static byte[] getBytes(String key) throws Exception {
		byte[] bytesVal = null;
		Jedis jedis = getJedis();

		if (jedis != null) {
			try {
				bytesVal = jedis.get(key.getBytes());
			} catch (Exception e) {
				logger.error("jedis.set error", e);
			} finally {
				if (jedis != null) {
					try {
						returnResource(jedis);
					} catch (Exception e1) {
						logger.error("returnResource error", e1);
					}
				}
			}
		}

		return bytesVal;
	}

	/**
	 * 批量获取byte[]类型的数据
	 * @param keyList
	 * @return
	 * @throws Exception
	 */
	public static List<byte[]> getBytesBatch(final List<String> keyList) throws Exception {
		List<byte[]> resultList = new ArrayList<byte[]>(keyList.size());
		Jedis jedis = getJedis();

		if (jedis == null) {
			return null;
		}

		List<Response<byte[]>> responseList = new ArrayList<Response<byte[]>>(keyList.size());

		try {
			Pipeline pipe = jedis.pipelined();

			for(String key : keyList) {
				responseList.add(pipe.get(key.getBytes()));
			}

			pipe.sync();

			for(Response<byte[]> response : responseList) {
				resultList.add(response.get());
			}
		} catch (Exception e) {
			logger.error("jedis.set error", e);
			throw e;
		} finally {
			if (jedis != null) {
				try {

					returnResource(jedis);
				} catch (Exception e1) {
					logger.error("returnResource error", e1);
				}
			}
		}

		return resultList;
	}

	public static byte[] getBytes(byte[] key) throws Exception {
		byte[] bytesVal = null;
		Jedis jedis = getJedis();

		if (jedis != null) {
			try {
				bytesVal = jedis.get(key);
			} catch (Exception e) {
				logger.error("jedis.set error", e);
			} finally {
				if (jedis != null) {
					try {
						returnResource(jedis);
					} catch (Exception e1) {
						logger.error("returnResource error", e1);
					}
				}
			}
		}

		return bytesVal;
	}

	/**
	 * 删除指定键值
	 * @param key
	 * @return
	 * @throws Exception
	 */
	public static long delKeys(String key) throws Exception{
		long retVal = 0l;
		Jedis jedis = getJedis();

		if (jedis != null) {
			try {
				retVal = jedis.del(key);
			} catch (Exception e) {
				logger.error("jedis.delKeys error", e);
			} finally {
				if (jedis != null) {
					try {
						returnResource(jedis);
					} catch (Exception e1) {
						logger.error("returnResource error", e1);
					}
				}
			}
		}

		return retVal;
	}

	/**
	 * 覆盖key对应的string的一部分
	 * @param key
	 * @param value
	 * @param offset
	 * @return
	 * @throws Exception
	 */
	public static long setRange(String key,String value,long offset) throws Exception{
		long retVal = 0l;
		Jedis jedis = getJedis();

		if (jedis != null) {
			try {
				retVal = jedis.setrange(key, offset, value);
			} catch (Exception e) {
				logger.error("jedis.setRange error", e);
			} finally {
				if (jedis != null) {
					try {
						returnResource(jedis);
					} catch (Exception e1) {
						logger.error("returnResource error", e1);
					}
				}
			}
		}

		return retVal;
	}

	/**
	 * 覆盖key对应的string的一部分
	 * @param key
	 * @param value
	 * @param offset
	 * @return
	 * @throws Exception
	 */
	public static long setByteRange(byte[] key,byte[] value,long offset) throws Exception{
		long retVal = 0l;
		Jedis jedis = getJedis();

		if (jedis != null) {
			try {
				retVal = jedis.setrange(key, offset, value);
			} catch (Exception e) {
				logger.error("jedis.setByteRange error", e);
			} finally {
				if (jedis != null) {
					try {
						returnResource(jedis);
					} catch (Exception e1) {
						logger.error("returnResource error", e1);
					}
				}
			}
		}

		return retVal;
	}

	/**
	 * 往指定队列左侧push数据
	 * @param key
	 * @param value
	 * @return
	 * @throws Exception
	 */
	public static long lPush(byte[] key,byte[] value) throws Exception{
		long retVal = 0l;
		Jedis jedis = getJedis();

		if (jedis != null) {
			try {
				retVal = jedis.lpush(key, value);
			} catch (Exception e) {
				logger.error("jedis.lPush error", e);
			} finally {
				if (jedis != null) {
					try {
						returnResource(jedis);
					} catch (Exception e1) {
						logger.error("returnResource error", e1);
					}
				}
			}
		}

		return retVal;
	}

	public static String lPop(String key) throws Exception {
		String retVal = "";
		Jedis jedis = getJedis();

		if (jedis != null) {
			try {
				retVal = jedis.lpop(key);
			} catch (Exception e) {
				logger.error("jedis.lPop error", e);
			} finally {
				if (jedis != null) {
					try {
						returnResource(jedis);
					} catch (Exception e1) {
						logger.error("returnResource error", e1);
					}
				}
			}
		}

		return retVal;
	}
	public static String rPop(String key) throws Exception {
		String retVal = "";
		Jedis jedis = getJedis();

		if (jedis != null) {
			try {
				retVal = jedis.rpop(key);
			} catch (Exception e) {
				logger.error("jedis.lPop error", e);
			} finally {
				if (jedis != null) {
					try {
						returnResource(jedis);
					} catch (Exception e1) {
						logger.error("returnResource error", e1);
					}
				}
			}
		}

		return retVal;
	}
	public static int llen(String key) throws Exception {
		Long retVal = 0l;
		Jedis jedis = getJedis();

		if (jedis != null) {
			try {
				retVal = jedis.llen(key);
			} catch (Exception e) {
				logger.error("jedis.lPop error", e);
			} finally {
				if (jedis != null) {
					try {
						returnResource(jedis);
					} catch (Exception e1) {
						logger.error("returnResource error", e1);
					}
				}
			}
		}

		return retVal.intValue();
	}

	public static void setTimeString(String key, String value) throws Exception {
		setString(key,timeout,value);
	}
}